package com.gta.edu.sdk.job.logtranfer;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.math.RandomUtils;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.gta.edu.sdk.common.dto.LogTranferDto;
import com.gta.edu.sdk.common.dto.LogTranferFileDto;
import com.gta.edu.sdk.util.StringUtil;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.SCPClient;
import ch.ethz.ssh2.Session;

@Component
public class LogTransferConfigJob {
	private static final Logger log = Logger.getLogger(LogTransferConfigJob.class);
	private static final String LOG_ROOT_PATH_XML = "LOG_HOME";
	private static int logKeepTimeLong;
	private Connection conn;
	private Session session;

	static {
		Properties prop = new Properties();
		InputStream is = null;
		try {
			is = LogTransferConfigJob.class.getClassLoader().getResourceAsStream("log_transfer_config.properties");
			prop.load(is);
			logKeepTimeLong = Integer.parseInt(prop.getProperty("log.keep.timelong"));
		} catch (Exception e) {
			log.error("定时任务从文件中读取配置信息失败", e);
		}
	}

	/**
	 * @description 保存本地15天的日志，清除15天以外的日志文件
	 * @author fengya
	 * @date 2021年1月26日 上午9:05:41
	 * void
	 */
	@Scheduled(cron = "0 0 1 ? * MON")
	public void logClear() {
		try {
			Calendar c = Calendar.getInstance();
			c.set(Calendar.DAY_OF_MONTH, c.get(Calendar.DAY_OF_MONTH) - logKeepTimeLong);
			String expireDate = new SimpleDateFormat("yyyyMMdd").format(c.getTime());
			String logRootPath = this.getLogRootPath();
			if (!StringUtil.isNullOrEmpty(logRootPath)) {
				File file = new File(logRootPath);
				File[] files = file.listFiles();
				if (files != null) {
					List<File> logFiles = Arrays.asList(files);
					for (File logFile : logFiles) {
						if (this.isExpire(expireDate, logFile.getName())) {
							logFile.delete();
						}
					}
				}
			}
		} catch (Exception e) {
			log.error("清理本地日志出现了异常：", e);
		}
	}

	private boolean isExpire(String expireDate,String fileName) {
		String pattern = "\\D+(\\d+)\\D+";
		Pattern p = Pattern.compile(pattern);
		Matcher m = p.matcher(fileName);
		if (m.find()) {
			String matchStr = m.group(1);
			if (matchStr.compareTo(expireDate) < 0) {
				return true;
			}
		}
		return false;
	}

	@Scheduled(cron = "0 0/30 * * * ?")
	public void logTransfer() {
		log.info("*******************************日志传输开始*****************************");
		// 获取日志存放的绝对路径
		try {
			String logRootPath = this.getLogRootPath();
			if (!StringUtil.isNullOrEmpty(logRootPath)) {
				List<LogTranferFileDto> fileList = this.getRemoteFiles();
				File file = new File(logRootPath);
				File[] files = file.listFiles();
				if (files != null) {
					List<File> logFiles = Arrays.asList(files);
					boolean isExists = false;
					String hostAddress = InetAddress.getLocalHost().getHostAddress();
					String remoteFileName = null;
					for (File logFile : logFiles) {
						isExists = this.isExists(logFile, fileList, hostAddress);
						if (!isExists) {
							remoteFileName = hostAddress + "-" + logFile.getName();
							this.tranferFile(logFile.getPath(), remoteFileName);
						}
					}
				}
			} else {
				log.info("**************************未正确配置日志的根目录，请检查！！！*******************");
				return;
			}
		} catch (Exception e) {
			log.error("日志传输出现了异常：", e);
		}
		log.info("*******************************日志传输结束*****************************");
	}

	/**
	 * 进行文件传输
	 * 2020年5月20日 下午2:59:49
	 * @user fengya
	 * @return void
	 * @throws Exception
	 */
	private void tranferFile(String localFileName,String remoteFileName) throws Exception {
		try {
			this.getConnection();
			SCPClient client = new SCPClient(conn);
			log.info("传输的文件：" + remoteFileName);
			client.put(localFileName, remoteFileName, LogTranferDto.getInstance().getRemoteLogRootPath(), "0600");
		} finally {
			this.closeConnection();
		}
	}

	private boolean isExists(File localLogFile, List<LogTranferFileDto> fileList, String hostAddress) {
		boolean isExists = false;
		for (LogTranferFileDto dto : fileList) {
			if (dto.getFilelName().equals(hostAddress + "-" + localLogFile.getName()) && dto.getFileSize() >= localLogFile.length()) {
				isExists = true;
			}
		}
		return isExists;
	}

	/**
	 * 解析Log4j中的配置信息，获取日志生成的根目录
	 * 2020年5月20日 下午2:58:38
	 * @user fengya
	 * @return
	 * @throws
	 * @return StringDocumentException
	 */
	private String getLogRootPath() throws DocumentException {
		InputStream is = LogTransferConfigJob.class.getClassLoader().getResourceAsStream("logback.xml");
		Document document = new SAXReader().read(is);
		Element root = document.getRootElement();
		Iterator<Element> iterator = root.elementIterator("property");
		while (iterator.hasNext()) {
			Element next = iterator.next();
			String attrName = next.attributeValue("name");
			if (LOG_ROOT_PATH_XML.equals(attrName)) {
				return next.attributeValue("value");
			}
		}
		return null;
	}

	/**
	 * 获取连接和会话 2020年5月20日 下午2:50:56
	 *
	 * @user fengya
	 * @param @throws Exception
	 * @return void
	 */
	private void getConnection() throws Exception {
		conn = new Connection(LogTranferDto.getInstance().getRemoteIp(), LogTranferDto.getInstance().getRemotePort());
		int randNum = RandomUtils.nextInt(600);
		Thread.sleep(randNum * 1000);
		conn.connect();
		// 鐧诲綍
		boolean isAuthenticated = conn.authenticateWithPassword(LogTranferDto.getInstance().getRemoteUserName(), LogTranferDto.getInstance().getRemotePassword());
		if (isAuthenticated == false) {
			throw new Exception("用户登录远程服务器失败！");
		}
		session = conn.openSession();
	}

	/**
	 * 关闭连接和会话 2020年5月20日 下午2:53:41
	 *
	 * @user fengya
	 * @param
	 * @return void
	 */
	private void closeConnection() {
		if (this.session != null) {
			this.session.close();
			this.session = null;
		}
		if (this.conn != null) {
			conn.close();
			conn = null;
		}
	}

	/**
	 * 获取远程服务器的文件列表数据
	 * 2020年5月20日 下午2:57:02
	 * @user fengya
	 * @throws Exception
	 * @return List<LogTranferFileDto>
	 */
	private List<LogTranferFileDto> getRemoteFiles() throws Exception {
		List<LogTranferFileDto> list = new ArrayList<LogTranferFileDto>();
		try {
			this.getConnection();
			this.session.execCommand("wc -c " + LogTranferDto.getInstance().getRemoteLogRootPath() + "/*");
			InputStream stdout = this.session.getStdout();
			BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stdout));
			LogTranferFileDto dto = null;
			String fileInfo = null;
			while ((fileInfo = bufferedReader.readLine()) != null) {
				if (!StringUtil.isNullOrEmpty(fileInfo) && fileInfo.contains(".log")) {
					dto = this.getLogTranferFileDto(fileInfo);
					if (dto != null) {
						list.add(dto);
					}
				}
			}
		} finally {
			this.closeConnection();
		}
		return list;
	}

	/**
	 * 解析文件信息获取文件名和文件大小
	 * 2020年5月20日 下午2:57:56
	 * @user fengya
	 * @param fileInfo
	 * @return
	 * @return LogTranferFileDto
	 */
	private LogTranferFileDto getLogTranferFileDto(String fileInfo) {
		String filelName = null;
		long fileSize = 0;
		String[] fileStrings = fileInfo.trim().split(" ");
		if (fileStrings.length == 2) {
			fileSize = Long.parseLong(fileStrings[0].trim());
			filelName = fileStrings[1].trim().replace(LogTranferDto.getInstance().getRemoteLogRootPath() + "/", "");
			return new LogTranferFileDto(filelName, fileSize);
		}
		return null;
	}

}
